package server.billing;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.rmi.NoSuchObjectException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * Class is the local implementation of the BillingServer Interface. It
 * implements the functionality to login to a billing server.
 */
public class BillingServerImpl implements BillingServer {

	private static BillingServerSecure secure = null;

	/*
	 * (non-Javadoc)
	 * 
	 * @see server.billing.BillingServer#login(java.lang.String,
	 * java.lang.String)
	 */
	@Override
	public BillingServerSecure login(String username, String password)
			throws RemoteException {
		java.io.InputStream is = ClassLoader
				.getSystemResourceAsStream("./user.properties");
		if (is != null) {
			java.util.Properties props = new java.util.Properties();
			try {
				props.load(is);
				String md5Password = props.getProperty(username);
				if (md5Password == null) {
					return null;
				}
				if (md5Password.toUpperCase().equals(md5(password))) {
					if (secure == null) {
						secure = new BillingServerSecureImpl();
					}
					return secure;
				}
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		} else {
			System.err.println("ERROR: user property file does not exist.");
		}
		return null;
	} // end of login

	/**
	 * Closes the remote object to the secure billing server.
	 */
	public static void closeSecureRemoteObject() {
		if (secure == null) {
			return;
		}
		try {
			UnicastRemoteObject.unexportObject(secure, true);
		} catch (NoSuchObjectException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Calculates the hex code representation of a byte array.
	 * 
	 * @param array
	 *            The byte array to calculate the hex representation.
	 * @return The hex representation as a String.
	 */
	private static String hex(byte[] array) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < array.length; ++i) {
			sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100)
					.toUpperCase().substring(1, 3));
		}
		return sb.toString();
	} // end of hex

	/**
	 * Returns the md5 representation of a String message.
	 * 
	 * @param message
	 *            The message.
	 * @return The message as md5 hash.
	 */
	private static String md5(String message) {
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			return hex(md.digest(message.getBytes("CP1252")));
		} catch (NoSuchAlgorithmException e) {
		} catch (UnsupportedEncodingException e) {
		}
		return null;
	} // end of md5

}
